package com.example.demo.serviceImpl;


import com.example.demo.Client.TransportTemplate;
import com.example.demo.service.TransportService;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsRequest;
import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsResponse;
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
import org.elasticsearch.action.bulk.BulkRequestBuilder;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.client.Requests;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.springframework.stereotype.Service;

import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;

@Service
public class TransportServiceImpl implements TransportService {

    //本类中常量(public是整个项目)
    private static TransportClient client = TransportTemplate.getClient();
    private static ObjectMapper mapper  = new ObjectMapper();

    @Override
    public void addIndex(String index, String type, String json) {
//        json格式如下
//        json = "{" +
//                "\"name\":\"深入浅出Node.js\"," +
//                "\"author\":\"朴灵 \"," +
//                "\"pubinfo\":\"人民邮电出版社 \"," +
//                "\"pubtime\":\"2013-12-1 \"," +
//                "\"desc\":\"本书从不同的视角介绍了 Node 内在的特点和结构。由首章Node 介绍为索引，涉及Node 的各个方面，主要内容包含模块机制的揭示、异步I/O 实现原理的展现、异步编程的探讨、内存控制的介绍、二进制数据Buffer 的细节、Node 中的网络编程基础、Node 中的Web 开发、进程间的消息传递、Node 测试以及通过Node 构建产品需要的注意事项。最后的附录介绍了Node 的安装、调试、编码规范和NPM 仓库等事宜。本书适合想深入了解 Node 的人员阅读。\"" +
//                "}";

        if(!StringUtils.isBlank(index) && (!StringUtils.isBlank(type)) ){
            client.prepareIndex(index,type).setSource(json).get();
        }
        TransportTemplate.closeClient();

    }

    @Override
    public void addIndex(String index, String type, Map<String, Object> map) {
        //map格式：
//        map = new HashMap<String, Object>();
//        map.put("name","Go Web编程");
//        map.put("author","谢孟军 ");
//        map.put("pubinfo","电子工业出版社");
//        map.put("pubtime","2013-6");
//        map.put("desc","《Go Web编程》介绍如何使用Go语言编写Web，包含了Go语言的入门、Web相关的一些知识、Go中如何处理Web的各方面设计（表单、session、cookie等）、数据库以及如何编写GoWeb应用等相关知识。通过《Go Web编程》的学习能够让读者了解Go的运行机制，如何用Go编写Web应用，以及Go的应用程序的部署和维护等，让读者对整个的Go的开发了如指掌。");
        if(!StringUtils.isBlank(index) && (!StringUtils.isBlank(type)) ) {
            client.prepareIndex(index, type).setSource(map).execute().actionGet();
            TransportTemplate.closeClient();
        }
    }

    @Override
    public void addIndex(String index, String type, Object object) {
//        Goods goods = new Goods();
//        goods.setId(1);
//        goods.setName("小胖"+1);
//        goods.setDesc("可爱的"+1+"好玩的有趣的");
//        goods.setLowerPrice(100);
//        goods.setHighPrice(200);
//        Type type1 = new Type();
//        type1.setModel("a-"+1);
//        type1.setColor("什么都会有的全文服务器搜索引擎");
//        type1.setSize(18);
//        goods.setContent(type1);
        ObjectMapper mapper  = new ObjectMapper();
        if(!StringUtils.isBlank(index) && (!StringUtils.isBlank(type)) ){
            try {
                client.prepareIndex(index,type).setSource(mapper.writeValueAsString(object)).get();
                TransportTemplate.closeClient();
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
        }


    }

    @Override
    public void addIndex(String index, String type, XContentBuilder builder) {
        if(!StringUtils.isBlank(index) && (!StringUtils.isBlank(type)) ){
            client.prepareIndex(index,type).setSource(builder).get();
            TransportTemplate.closeClient();
        }
    }

    @Override
    public void addIndex(String index) {
        if(!StringUtils.isBlank(index)){}
        client.admin().indices().prepareCreate(index).get();
        TransportTemplate.closeClient();
    }

    @Override
    public IndexResponse getIndexResponse(String index, String type, XContentBuilder builder) {
        if(!StringUtils.isBlank(index) && (!StringUtils.isBlank(type)) ){
            IndexResponse indexResponse = client.prepareIndex(index, type).setSource(builder).get();
            TransportTemplate.closeClient();
            return indexResponse;
        }
        return null;

    }

    @Override
    public void printIndexInfo(IndexResponse response) {
        if(response !=null){
            String index = response.getIndex();
            String type = response.getType();
            String id = response.getId();
            long version = response.getVersion();
            RestStatus status = response.status();
            System.out.println("index索引："+index + "--类型：" + type + "--索引id：" + id + "--版本：" + version + "--状态：" + status);
            TransportTemplate.closeClient();
        }

    }

    @Override
    public void addIndexByIK(String index, String type, XContentBuilder builder) {
        if(!StringUtils.isBlank(index) && (!StringUtils.isBlank(type)) ){
            //创建索引
            client.admin().indices().prepareCreate(index).get();
            // 创建映射
            PutMappingRequest mapping = Requests.putMappingRequest(index)
                    .type(type).source(builder);
            try {
                client.admin().indices().putMapping(mapping).get();
                TransportTemplate.closeClient();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    }

    @Override
    public void deleteIndex(String index , String type, String id) {
        if (!StringUtils.isBlank(index) && (!StringUtils.isBlank(type))&& (!StringUtils.isBlank(id))) {
            client.prepareDelete(index, type, id)
                    .execute()
                    .actionGet();
            TransportTemplate.closeClient();
        }
    }

    @Override
    public void deleteIndex(String index) {
        if (isIndexExists(index)) {
            client.admin().indices().prepareDelete(index)
                    .execute().actionGet();
            TransportTemplate.closeClient();
        }

    }

    @Override
    public void getIndex(String index, String type, String id) {
        GetResponse getresponse = client.prepareGet(index, type, id).execute().actionGet();
        System.out.println(getresponse.getSourceAsString());
        TransportTemplate.closeClient();
    }

    @Override
    public void insertByObject(String index, String type, Object object) {
        if(object !=null){
            try {
                client.prepareIndex(index, type).setSource(mapper.writeValueAsString(object)).get();
                TransportTemplate.closeClient();

            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
        }

    }

    @Override
    public void insertByObject(String index, String type, String id, Object object) {
        if(object !=null){
            try {
                client.prepareIndex(index, type,id).setSource(mapper.writeValueAsString(object)).get();
                TransportTemplate.closeClient();

            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void batchInsert(String index, String type, List<?> objects) {
        if(objects !=null && objects.size()>0){
            BulkRequestBuilder bulkRequest = client.prepareBulk();
            for(Object object:objects){
                bulkRequest.add(client.prepareIndex(index,type).setSource(object)).execute().actionGet();
            }
            TransportTemplate.closeClient();
        }
    }

    @Override
    public void batchInsert(String index, String type, String id, List<?> objects) {
        if(objects !=null && objects.size()>0){
            BulkRequestBuilder bulkRequest = client.prepareBulk();
            for(Object object:objects){
                bulkRequest.add(client.prepareIndex(index, type, id).setSource(object)).execute().actionGet();

            }
            TransportTemplate.closeClient();
        }
    }

    @Override
    public void batchInsert(String index, String type, Map<String, Object> map) {
        if(map !=null && map.size()>0){
            BulkRequestBuilder bulkRequest = client.prepareBulk();
            bulkRequest.add(client.prepareIndex(index, type).setSource(map)).execute().actionGet();
            TransportTemplate.closeClient();

        }
    }

    @Override
    public void batchInsert(String index, String type, String id, Map<String, Object> map) {
        if(map !=null && map.size()>0){
            BulkRequestBuilder bulkRequest = client.prepareBulk();
            bulkRequest.add(client.prepareIndex(index, type,id).setSource(map)).execute().actionGet();
            TransportTemplate.closeClient();

        }
    }

    @Override
    public void updateDocument(String index, String type, String id, Object object) {
        if(object!=null){
            try {
                client.update(new UpdateRequest(index, type, id).doc(mapper.writeValueAsString(object))).get();
                TransportTemplate.closeClient();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    }

    @Override
    public SearchResponse getMatchAll(String index, String type)

    {
        if (!StringUtils.isBlank(index) && (!StringUtils.isBlank(type))) {
            SearchResponse searchResponse = client.prepareSearch(index)
                    .setTypes(type).setQuery(QueryBuilders.matchAllQuery())
                    .get();
            TransportTemplate.closeClient();
            return searchResponse;
        }
        return null;

    }

    @Override
    public void printSearchResponse(SearchResponse searchResponse) {

        if(searchResponse!=null){
            // 获取命中次数，查询结果有多少对象
            SearchHits hits = searchResponse.getHits();
            System.out.println("查询结果有：" + hits.getTotalHits() + "条");
            Iterator<SearchHit> iterator = hits.iterator();
            while (iterator.hasNext()) {
                // 每个查询对象
                SearchHit searchHit = iterator.next();
                System.out.println(searchHit.getSourceAsString()); // 获取字符串格式打印
            }
            TransportTemplate.closeClient();
        }
    }

    @Override
    public SearchResponse queryStringQuery(String index, String type, String terms) {
        if (!StringUtils.isBlank(index) && (!StringUtils.isBlank(type))) {
            if(!StringUtils.isBlank(terms)){
                SearchResponse searchResponse = client.prepareSearch(index)
                        .setTypes(type).setQuery(QueryBuilders.queryStringQuery(terms))
                        .get();
                return searchResponse;
            }else{
                //为null或者空格的情况下查询所有记录
                SearchResponse searchResponse = client.prepareSearch(index)
                        .setTypes(type).setQuery(QueryBuilders.matchAllQuery())
                        .get();
                return searchResponse;
            }
        }
        return null;

    }

    // 判断索引是否存在 传入参数为索引库名称
    public static boolean isIndexExists(String indexName) {
        boolean flag = false;
        try {
            IndicesExistsRequest inExistsRequest = new IndicesExistsRequest(indexName);
            IndicesExistsResponse inExistsResponse = client.admin().indices()
                    .exists(inExistsRequest).actionGet();

            if (inExistsResponse.isExists()) {
                flag = true;
            } else {
                flag = false;
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return flag;
    }

}
